package com.basker.pisces.domain.element;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import com.basker.pisces.core.serialize.xml.BeanXmlSerializeHandler;
import com.basker.pisces.core.serialize.xml.DataContractXmlSerializer;
import com.basker.pisces.domain.element.meta.MetaType;
import com.basker.pisces.domain.element.resouce.MetaTypeBuilder;

public class MetaTypeManager {

    private static final Map<String, MetaType> META_TYPE_MAP = new HashMap<>();
    private static final Logger LOGGER = LoggerFactory.getLogger(MetaTypeManager.class);

    public synchronized static void build(Resource[] resources) throws IOException {
        if (ObjectUtils.isEmpty(resources)) {
            return;
        }

        META_TYPE_MAP.clear();

        DataContractXmlSerializer builderXmlSerializer = new DataContractXmlSerializer(
                new BeanXmlSerializeHandler(MetaTypeBuilder.class));
        DataContractXmlSerializer metaTypeXmlSerializer = new DataContractXmlSerializer(
                new BeanXmlSerializeHandler(MetaType.class));

        List<MetaTypeBuilder> builders = new ArrayList<>(resources.length);

        for (Resource resource : resources) {
            URL url = resource.getURL();
            MetaTypeBuilder builder = (MetaTypeBuilder) builderXmlSerializer.deserializeFromUrl(url);

            builders.add(builder);
        }

        for (MetaTypeBuilder builder : builders) {
            String metaTypeName = builder.getMetaType();
            List<String> resouceList = builder.getResouceList();

            if (CollectionUtils.isEmpty(resouceList)) {
                if (LOGGER.isWarnEnabled()) {
                    LOGGER.warn("'" + metaTypeName + "' has no resouces!");
                }

                continue;
            }

            MetaType metaType = null;

            for (String res : resouceList) {
                if (!res.startsWith("metatype")) {
                    res = "metatype/" + res;
                }

                URL url = MetaTypeManager.class.getClassLoader().getResource(res);

                if (url == null) {
                    if (LOGGER.isWarnEnabled()) {
                        LOGGER.warn("'" + res + "' not found!");
                    }

                    continue;
                }

                metaType = (MetaType) metaTypeXmlSerializer.deserializeFromUrl(url, metaType);
            }

            if (metaType == null) {
                throw new IllegalStateException("metaType is null!");
            }

            metaTypeName = metaType.getName();
            if (META_TYPE_MAP.containsKey(metaTypeName)) {
                throw new RuntimeException("'" + metaTypeName + "' is already exist!");
            }

            metaType.build();

            META_TYPE_MAP.put(metaTypeName, metaType);
        }
    }

    public static MetaType getMetaType(String metaTypeName) {
        return META_TYPE_MAP.get(metaTypeName);
    }

}
